package com.liang.manage.auth.facade.server.iml;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.liang.manage.auth.facade.dto.permissions.PermissionsDTO;
import com.liang.manage.auth.facade.dto.permissions.PermissionsSearchDTO;
import com.liang.manage.auth.facade.dto.role.RolePermissionsDTO;
import com.liang.manage.auth.facade.entity.PermissionsPo;
import com.liang.manage.auth.facade.entity.PermissionsPoExample;
import com.liang.manage.auth.facade.mapper.PermissionsPoMapper;
import com.liang.manage.auth.facade.mapstruct.PermissionsMS;
import com.liang.manage.auth.facade.mapstruct.PermissionsSsoMS;
import com.liang.manage.auth.facade.server.*;

import com.liang.nansheng.common.auth.PermissionsSsoDTO;
import com.liang.nansheng.common.auth.UserSsoDTO;
import com.liang.nansheng.common.enums.ResponseCode;
import com.liang.nansheng.common.web.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author 马亮
 * @date 2021/4/23 17:28
 */
@Slf4j
@Service
@Component
public class PermissionsServiceImpl implements PermissionsService {
    @Autowired
    private PermissionsPoMapper permissionsPoMapper;

    @Autowired
    private RoleService roleService;

    @Autowired
    private RolePermissionsService rolePermissionsService;

    @Autowired
    private UserService userService;

    @Autowired
    private ProjectService projectService;

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 新增权限
     *
     * @param permissionsDTO
     * @param currentUser
     * @return
     */
    @Override
    public Boolean create(PermissionsDTO permissionsDTO, UserSsoDTO currentUser) {
        if (StringUtils.isBlank(permissionsDTO.getApi()) || StringUtils.isBlank(permissionsDTO.getDesc()) || permissionsDTO.getProjectId() == null) {
            throw BusinessException.build(ResponseCode.NOT_EXISTS, "参数不合规");
        }
        if (isApiExist(null, permissionsDTO.getApi())) {
            throw BusinessException.build(ResponseCode.NAME_EXIST, "权限代码重复");
        }
        permissionsDTO.setState(true);
        permissionsDTO.setIsDeleted(false);
        permissionsDTO.setCreateUser(currentUser.getUserId());
        permissionsDTO.setUpdateUser(currentUser.getUserId());
        LocalDateTime now = LocalDateTime.now();
        permissionsDTO.setCreateTime(now);
        permissionsDTO.setUpdateTime(now);
        if (permissionsPoMapper.insertSelective(PermissionsMS.INSTANCE.toPo(permissionsDTO)) <= 0) {
            throw BusinessException.build(ResponseCode.OPERATE_FAIL, "新增权限失败");
        }

        return true;
    }

    /**
     * 权限代码判重
     *
     * @param api
     * @param permissionsId
     * @return
     */
    @Override
    public Boolean isValidPermissions(String api, Integer permissionsId) {
        // 已存在
        if (isApiExist(permissionsId, api)) {
            throw BusinessException.build(ResponseCode.NAME_EXIST, "权限代码已存在");
        }
        return true;
    }

    /**
     * 根据id获取权限信息
     *
     * @param id
     * @return
     */
    @Override
    public PermissionsSsoDTO getSsoById(Integer id) {
        return PermissionsSsoMS.INSTANCE.toDTO(permissionsPoMapper.selectByPrimaryKey(id));
    }

    /**
     * 分页获取权限
     *
     * @param permissionsSearchDTO
     * @return
     */
    @Override
    public PageInfo<PermissionsDTO> getList(PermissionsSearchDTO permissionsSearchDTO) {
        PageHelper.startPage(permissionsSearchDTO.getCurrent(), permissionsSearchDTO.getSize());

        PermissionsPoExample example = new PermissionsPoExample();
        PermissionsPoExample.Criteria criteria = example.createCriteria().andIsDeletedEqualTo(false);
        if (permissionsSearchDTO.getProjectId() != null) {
            criteria.andProjectIdEqualTo(permissionsSearchDTO.getProjectId());
        }
        if (StringUtils.isNotBlank(permissionsSearchDTO.getApi())) {
            criteria.andApiLike("%" + permissionsSearchDTO.getApi() + "%");
        }
        if (StringUtils.isNotBlank(permissionsSearchDTO.getDesc())) {
            criteria.andDescLike("%" + permissionsSearchDTO.getDesc() + "%");
        }
        if (permissionsSearchDTO.getState() != null) {
            criteria.andStateEqualTo(permissionsSearchDTO.getState());
        }
        example.setOrderByClause("`id` desc");

        List<PermissionsPo> permissionsPos = permissionsPoMapper.selectByExample(example);
        PageInfo<PermissionsDTO> pageInfo = PermissionsMS.INSTANCE.toPage(new PageInfo<>(permissionsPos));
        // 通过id获取name
        pageInfo.getList().forEach(permissionsDTO -> {
            permissionsDTO.setCreateUserName(userService.getNameByIdFromRedis(permissionsDTO.getCreateUser()));
            permissionsDTO.setUpdateUserName(userService.getNameByIdFromRedis(permissionsDTO.getUpdateUser()));
            permissionsDTO.setProjectName(projectService.getNameByIdFromRedis(permissionsDTO.getProjectId()));
        });

        return pageInfo;
    }

    /**
     * 更新权限
     *
     * @param permissionsDTO
     * @param currentUser
     * @return
     */
    @Override
    public Boolean update(PermissionsDTO permissionsDTO, UserSsoDTO currentUser) {
        if (StringUtils.isBlank(permissionsDTO.getApi()) || StringUtils.isBlank(permissionsDTO.getDesc())) {
            throw BusinessException.build(ResponseCode.NOT_EXISTS, "参数不合规");
        }
        if (isApiExist(permissionsDTO.getId(), permissionsDTO.getApi())) {
            throw BusinessException.build(ResponseCode.NAME_EXIST, "权限代码重复");
        }
        permissionsDTO.setState(null);
        permissionsDTO.setIsDeleted(null);
        permissionsDTO.setCreateUser(null);
        permissionsDTO.setCreateTime(null);
        permissionsDTO.setUpdateUser(currentUser.getUserId());
        permissionsDTO.setUpdateTime(LocalDateTime.now());
        if (permissionsPoMapper.updateByPrimaryKeySelective(PermissionsMS.INSTANCE.toPo(permissionsDTO)) <= 0) {
            throw BusinessException.build(ResponseCode.OPERATE_FAIL, "更新权限失败");
        }

        return true;
    }

    /**
     * 删除权限
     *
     * @param ids
     * @param currentUser
     * @return
     */
    @Override
    public Boolean delete(List<Integer> ids, UserSsoDTO currentUser) {
        for (Integer id : ids) {
            PermissionsDTO permissionsDTO = new PermissionsDTO();
            permissionsDTO.setId(id);
            permissionsDTO.setIsDeleted(true);
            permissionsDTO.setUpdateTime(LocalDateTime.now());
            permissionsDTO.setUpdateUser(currentUser.getUserId());
            if (permissionsPoMapper.updateByPrimaryKeySelective(PermissionsMS.INSTANCE.toPo(permissionsDTO)) <= 0) {
                throw BusinessException.build(ResponseCode.OPERATE_FAIL, "删除权限失败");
            }

            // 移除对应的角色权限
            List<RolePermissionsDTO> rolePermissionsDTOS = rolePermissionsService.getByPermissionsId(id);
            if (CollectionUtils.isNotEmpty(rolePermissionsDTOS)) {
                rolePermissionsService.deleteByPermissionsId(id, currentUser);
            }
        }

        return true;
    }

    /**
     * 通过角色id分页获取所有权限
     *
     * @param permissionsSearchDTO
     * @return
     */
    @Override
    public PageInfo<PermissionsDTO> getAllByRoleId(PermissionsSearchDTO permissionsSearchDTO) {
        if (permissionsSearchDTO.getRoleId() == null || permissionsSearchDTO.getProjectId() == null) {
            throw BusinessException.build(ResponseCode.NOT_EXISTS, "参数不合规");
        }
        // 根据角色id获取角色权限信息
        List<RolePermissionsDTO> rolePermissionsDTOS = rolePermissionsService.getByRoleId(permissionsSearchDTO.getRoleId());
        List<Integer> roleRights = rolePermissionsDTOS.stream().map(RolePermissionsDTO::getPermissionsId).collect(Collectors.toList());

        // 按系统id分页获取权限信息
        PageInfo<PermissionsDTO> dtoPageInfo = getList(permissionsSearchDTO);

        for (PermissionsDTO permissionsDTO : dtoPageInfo.getList()) {
            // 角色权限包含该权限
            permissionsDTO.setHasAdd(roleRights.contains(permissionsDTO.getId()));
        }

        return dtoPageInfo;
    }

    /**
     * 按项目ID获取权限
     *
     * @param projectId
     * @return
     */
    @Override
    public List<PermissionsDTO> getRightsByProjectId(Integer projectId) {
        PermissionsPoExample example = new PermissionsPoExample();
        example.createCriteria().andIsDeletedEqualTo(false)
                .andStateEqualTo(true)
                .andProjectIdEqualTo(projectId);

        return PermissionsMS.INSTANCE.toDTO(permissionsPoMapper.selectByExample(example));
    }

    /**
     * 判断权限api是否已经存在
     *
     * @param permissionsId 权限id
     * @param api           权限字符串(api)
     * @return
     */
    private boolean isApiExist(Integer permissionsId, String api) {
        PermissionsPoExample example = new PermissionsPoExample();
        example.createCriteria().andIsDeletedEqualTo(false)
                .andApiEqualTo(api);
        List<PermissionsPo> permissionsPos = permissionsPoMapper.selectByExample(example);
        if (permissionsPos.size() > 1) {
            return true;
        } else if (permissionsPos.size() == 1) {
            // 更新时permissionsId是有值的
            return !permissionsPos.get(0).getId().equals(permissionsId);
        }
        return false;
    }

}